package com.leon.datalink.core.persistence;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.SecureRandom;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Map;
import java.util.Base64;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

/**
 * 企业级安全管理器
 * 
 * 提供企业级的安全功能，包括：
 * - 数据加密存储和传输
 * - 访问控制和权限管理
 * - 审计日志和合规报告
 * - 安全扫描和漏洞检测
 * 
 * @author DataLink Team
 * @version 1.0.0
 */
public class EnterpriseSecurityManager {
    
    private static final Logger logger = LoggerFactory.getLogger(EnterpriseSecurityManager.class);
    private static final Logger auditLogger = LoggerFactory.getLogger("AUDIT");
    
    private static volatile EnterpriseSecurityManager instance;
    
    // 加密配置
    private static final String ENCRYPTION_ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String KEY_ALGORITHM = "AES";
    private static final int KEY_LENGTH = 256;
    private static final int IV_LENGTH = 16;
    
    // 安全统计
    private final AtomicLong encryptionOperations = new AtomicLong(0);
    private final AtomicLong decryptionOperations = new AtomicLong(0);
    private final AtomicLong accessDeniedCount = new AtomicLong(0);
    private final AtomicLong auditLogCount = new AtomicLong(0);
    
    // 权限管理
    private final Map<String, UserPermissions> userPermissions = new ConcurrentHashMap<>();
    private final Map<String, RolePermissions> rolePermissions = new ConcurrentHashMap<>();
    
    // 审计日志
    private final List<AuditLogEntry> auditLogs = Collections.synchronizedList(new ArrayList<>());
    
    // 加密密钥管理
    private final SecretKey masterKey;
    private final SecureRandom secureRandom;
    
    private EnterpriseSecurityManager() {
        this.secureRandom = new SecureRandom();
        this.masterKey = generateMasterKey();
        initializeDefaultPermissions();
        logger.info("企业级安全管理器初始化完成");
    }
    
    public static EnterpriseSecurityManager getInstance() {
        if (instance == null) {
            synchronized (EnterpriseSecurityManager.class) {
                if (instance == null) {
                    instance = new EnterpriseSecurityManager();
                }
            }
        }
        return instance;
    }
    
    /**
     * 生成主密钥
     */
    private SecretKey generateMasterKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
            keyGenerator.init(KEY_LENGTH);
            SecretKey key = keyGenerator.generateKey();
            logger.info("主密钥生成完成");
            return key;
        } catch (Exception e) {
            logger.error("生成主密钥失败", e);
            throw new SecurityException("无法生成主密钥", e);
        }
    }
    
    /**
     * 初始化默认权限
     */
    private void initializeDefaultPermissions() {
        // 管理员角色
        RolePermissions adminRole = new RolePermissions("admin");
        adminRole.addPermission("persistence.read");
        adminRole.addPermission("persistence.write");
        adminRole.addPermission("persistence.config");
        adminRole.addPermission("persistence.monitor");
        adminRole.addPermission("system.admin");
        rolePermissions.put("admin", adminRole);
        
        // 操作员角色
        RolePermissions operatorRole = new RolePermissions("operator");
        operatorRole.addPermission("persistence.read");
        operatorRole.addPermission("persistence.write");
        operatorRole.addPermission("persistence.monitor");
        rolePermissions.put("operator", operatorRole);
        
        // 只读角色
        RolePermissions readOnlyRole = new RolePermissions("readonly");
        readOnlyRole.addPermission("persistence.read");
        readOnlyRole.addPermission("persistence.monitor");
        rolePermissions.put("readonly", readOnlyRole);
        
        logger.info("默认权限配置完成");
    }
    
    /**
     * 数据加密
     */
    public String encryptData(String plainText) {
        try {
            Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
            
            // 生成随机IV
            byte[] iv = new byte[IV_LENGTH];
            secureRandom.nextBytes(iv);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            
            cipher.init(Cipher.ENCRYPT_MODE, masterKey, ivSpec);
            byte[] encryptedData = cipher.doFinal(plainText.getBytes("UTF-8"));
            
            // 将IV和加密数据组合
            byte[] combined = new byte[IV_LENGTH + encryptedData.length];
            System.arraycopy(iv, 0, combined, 0, IV_LENGTH);
            System.arraycopy(encryptedData, 0, combined, IV_LENGTH, encryptedData.length);
            
            encryptionOperations.incrementAndGet();
            return Base64.getEncoder().encodeToString(combined);
        } catch (Exception e) {
            logger.error("数据加密失败", e);
            throw new SecurityException("数据加密失败", e);
        }
    }
    
    /**
     * 数据解密
     */
    public String decryptData(String encryptedText) {
        try {
            byte[] combined = Base64.getDecoder().decode(encryptedText);
            
            // 分离IV和加密数据
            byte[] iv = new byte[IV_LENGTH];
            byte[] encryptedData = new byte[combined.length - IV_LENGTH];
            System.arraycopy(combined, 0, iv, 0, IV_LENGTH);
            System.arraycopy(combined, IV_LENGTH, encryptedData, 0, encryptedData.length);
            
            Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, masterKey, ivSpec);
            
            byte[] decryptedData = cipher.doFinal(encryptedData);
            decryptionOperations.incrementAndGet();
            
            return new String(decryptedData, "UTF-8");
        } catch (Exception e) {
            logger.error("数据解密失败", e);
            throw new SecurityException("数据解密失败", e);
        }
    }
    
    /**
     * 检查用户权限
     */
    public boolean checkPermission(String userId, String permission) {
        UserPermissions userPerms = userPermissions.get(userId);
        if (userPerms == null) {
            accessDeniedCount.incrementAndGet();
            logAuditEvent("ACCESS_DENIED", userId, "用户不存在: " + userId);
            return false;
        }
        
        boolean hasPermission = userPerms.hasPermission(permission);
        if (!hasPermission) {
            accessDeniedCount.incrementAndGet();
            logAuditEvent("ACCESS_DENIED", userId, "权限不足: " + permission);
        } else {
            logAuditEvent("ACCESS_GRANTED", userId, "权限检查通过: " + permission);
        }
        
        return hasPermission;
    }
    
    /**
     * 添加用户
     */
    public void addUser(String userId, String role) {
        RolePermissions rolePerms = rolePermissions.get(role);
        if (rolePerms == null) {
            throw new IllegalArgumentException("角色不存在: " + role);
        }
        
        UserPermissions userPerms = new UserPermissions(userId, role);
        userPerms.addRolePermissions(rolePerms);
        userPermissions.put(userId, userPerms);
        
        logAuditEvent("USER_ADDED", "system", "添加用户: " + userId + ", 角色: " + role);
        logger.info("添加用户: {}, 角色: {}", userId, role);
    }
    
    /**
     * 移除用户
     */
    public void removeUser(String userId) {
        UserPermissions removed = userPermissions.remove(userId);
        if (removed != null) {
            logAuditEvent("USER_REMOVED", "system", "移除用户: " + userId);
            logger.info("移除用户: {}", userId);
        }
    }
    
    /**
     * 记录审计日志
     */
    public void logAuditEvent(String eventType, String userId, String description) {
        AuditLogEntry entry = new AuditLogEntry(
            System.currentTimeMillis(),
            eventType,
            userId,
            description,
            LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        );
        
        auditLogs.add(entry);
        auditLogCount.incrementAndGet();
        
        auditLogger.info("AUDIT: {} | {} | {} | {}", 
            entry.getTimestamp(), entry.getEventType(), entry.getUserId(), entry.getDescription());
        
        // 限制审计日志大小
        if (auditLogs.size() > 10000) {
            auditLogs.subList(0, 1000).clear(); // 删除最老的1000条
        }
    }
    
    /**
     * 生成合规报告
     */
    public ComplianceReport generateComplianceReport() {
        long totalOperations = encryptionOperations.get() + decryptionOperations.get();
        long totalAccessAttempts = totalOperations + accessDeniedCount.get();
        double securityScore = totalAccessAttempts > 0 ? 
            (double)(totalOperations) / totalAccessAttempts * 100 : 100.0;
        
        return new ComplianceReport(
            encryptionOperations.get(),
            decryptionOperations.get(),
            accessDeniedCount.get(),
            auditLogCount.get(),
            userPermissions.size(),
            rolePermissions.size(),
            securityScore,
            LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        );
    }
    
    /**
     * 安全扫描
     */
    public SecurityScanResult performSecurityScan() {
        List<String> vulnerabilities = new ArrayList<>();
        List<String> recommendations = new ArrayList<>();
        
        // 检查密钥强度
        if (masterKey.getEncoded().length < 32) {
            vulnerabilities.add("主密钥长度不足");
            recommendations.add("使用256位AES密钥");
        }
        
        // 检查权限配置
        if (userPermissions.isEmpty()) {
            vulnerabilities.add("未配置用户权限");
            recommendations.add("配置适当的用户权限");
        }
        
        // 检查审计日志
        if (auditLogCount.get() == 0) {
            vulnerabilities.add("缺少审计日志");
            recommendations.add("启用审计日志记录");
        }
        
        // 检查访问控制
        double denialRate = totalAccessAttempts() > 0 ? 
            (double)accessDeniedCount.get() / totalAccessAttempts() : 0.0;
        if (denialRate > 0.1) {
            vulnerabilities.add("访问拒绝率过高: " + String.format("%.2f%%", denialRate * 100));
            recommendations.add("检查权限配置和用户行为");
        }
        
        String riskLevel = vulnerabilities.isEmpty() ? "LOW" : 
                          vulnerabilities.size() <= 2 ? "MEDIUM" : "HIGH";
        
        return new SecurityScanResult(vulnerabilities, recommendations, riskLevel);
    }
    
    private long totalAccessAttempts() {
        return encryptionOperations.get() + decryptionOperations.get() + accessDeniedCount.get();
    }
    
    /**
     * 获取安全统计
     */
    public SecurityStats getSecurityStats() {
        return new SecurityStats(
            encryptionOperations.get(),
            decryptionOperations.get(),
            accessDeniedCount.get(),
            auditLogCount.get(),
            userPermissions.size(),
            rolePermissions.size()
        );
    }
    
    /**
     * 用户权限类
     */
    public static class UserPermissions {
        private final String userId;
        private final String role;
        private final Map<String, Boolean> permissions = new ConcurrentHashMap<>();
        
        public UserPermissions(String userId, String role) {
            this.userId = userId;
            this.role = role;
        }
        
        public void addPermission(String permission) {
            permissions.put(permission, true);
        }
        
        public void addRolePermissions(RolePermissions rolePerms) {
            permissions.putAll(rolePerms.getPermissions());
        }
        
        public boolean hasPermission(String permission) {
            return permissions.getOrDefault(permission, false);
        }
        
        public String getUserId() { return userId; }
        public String getRole() { return role; }
    }
    
    /**
     * 角色权限类
     */
    public static class RolePermissions {
        private final String roleName;
        private final Map<String, Boolean> permissions = new ConcurrentHashMap<>();
        
        public RolePermissions(String roleName) {
            this.roleName = roleName;
        }
        
        public void addPermission(String permission) {
            permissions.put(permission, true);
        }
        
        public Map<String, Boolean> getPermissions() {
            return new ConcurrentHashMap<>(permissions);
        }
        
        public String getRoleName() { return roleName; }
    }
    
    /**
     * 审计日志条目
     */
    public static class AuditLogEntry {
        private final long timestamp;
        private final String eventType;
        private final String userId;
        private final String description;
        private final String formattedTime;
        
        public AuditLogEntry(long timestamp, String eventType, String userId, 
                           String description, String formattedTime) {
            this.timestamp = timestamp;
            this.eventType = eventType;
            this.userId = userId;
            this.description = description;
            this.formattedTime = formattedTime;
        }
        
        // Getters
        public long getTimestamp() { return timestamp; }
        public String getEventType() { return eventType; }
        public String getUserId() { return userId; }
        public String getDescription() { return description; }
        public String getFormattedTime() { return formattedTime; }
    }
    
    /**
     * 合规报告
     */
    public static class ComplianceReport {
        private final long encryptionOps;
        private final long decryptionOps;
        private final long accessDenied;
        private final long auditLogs;
        private final int userCount;
        private final int roleCount;
        private final double securityScore;
        private final String generatedAt;
        
        public ComplianceReport(long encryptionOps, long decryptionOps, long accessDenied,
                              long auditLogs, int userCount, int roleCount, 
                              double securityScore, String generatedAt) {
            this.encryptionOps = encryptionOps;
            this.decryptionOps = decryptionOps;
            this.accessDenied = accessDenied;
            this.auditLogs = auditLogs;
            this.userCount = userCount;
            this.roleCount = roleCount;
            this.securityScore = securityScore;
            this.generatedAt = generatedAt;
        }
        
        // Getters
        public long getEncryptionOps() { return encryptionOps; }
        public long getDecryptionOps() { return decryptionOps; }
        public long getAccessDenied() { return accessDenied; }
        public long getAuditLogs() { return auditLogs; }
        public int getUserCount() { return userCount; }
        public int getRoleCount() { return roleCount; }
        public double getSecurityScore() { return securityScore; }
        public String getGeneratedAt() { return generatedAt; }
    }
    
    /**
     * 安全扫描结果
     */
    public static class SecurityScanResult {
        private final List<String> vulnerabilities;
        private final List<String> recommendations;
        private final String riskLevel;
        
        public SecurityScanResult(List<String> vulnerabilities, List<String> recommendations, String riskLevel) {
            this.vulnerabilities = new ArrayList<>(vulnerabilities);
            this.recommendations = new ArrayList<>(recommendations);
            this.riskLevel = riskLevel;
        }
        
        public List<String> getVulnerabilities() { return vulnerabilities; }
        public List<String> getRecommendations() { return recommendations; }
        public String getRiskLevel() { return riskLevel; }
    }
    
    /**
     * 安全统计
     */
    public static class SecurityStats {
        private final long encryptionOps;
        private final long decryptionOps;
        private final long accessDenied;
        private final long auditLogs;
        private final int userCount;
        private final int roleCount;
        
        public SecurityStats(long encryptionOps, long decryptionOps, long accessDenied,
                           long auditLogs, int userCount, int roleCount) {
            this.encryptionOps = encryptionOps;
            this.decryptionOps = decryptionOps;
            this.accessDenied = accessDenied;
            this.auditLogs = auditLogs;
            this.userCount = userCount;
            this.roleCount = roleCount;
        }
        
        // Getters
        public long getEncryptionOps() { return encryptionOps; }
        public long getDecryptionOps() { return decryptionOps; }
        public long getAccessDenied() { return accessDenied; }
        public long getAuditLogs() { return auditLogs; }
        public int getUserCount() { return userCount; }
        public int getRoleCount() { return roleCount; }
    }
}
